﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Web.Configuration;
using System.Web.Http;
using System.Web.Http.Controllers;
using Common.Logging;
using In.Api.Dto.HisWs;
using Newtonsoft.Json;
using OutDbContext;
using Rmq.Center;
using Senparc.Weixin.MP.TenPayLib;
using User.Api.BizExtensions;
using User.Api.Dto.Inpatient;
using User.Api.Helpers;
using User.Api.HttpClients;
using PayFailedResponse = User.Api.Dto.Inpatient.PayFailedResponse;

namespace User.Api.Controllers
{
    public class InpatientController : ApiController
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(InpatientController));
        private FsssdqfybjyEntities _ctx;

        private static readonly object OrderNoLocker = new object();
        private static readonly object PayNotifyLocker = new object();

        private static TenPayInfo _tenPayInfo;

        public static TenPayInfo TenPayInfo
        {
            get
            {
                if (_tenPayInfo == null)
                {
                    _tenPayInfo =
                        TenPayInfoCollection.Data[ConfigurationManager.AppSettings["WeixinPay_PartnerId"]];
                }
                return _tenPayInfo;
            }
        }

        protected override void Initialize(HttpControllerContext controllerContext)
        {
            _ctx = new FsssdqfybjyEntities();
            base.Initialize(controllerContext);
        }

        protected override void Dispose(bool disposing)
        {
            _ctx.Dispose();
            base.Dispose(disposing);
        }

        /// <summary>
        /// 获取当前住院记录，包含每天的费用记录
        /// </summary>
        /// <param name="wardId"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetInpatient")]
        public GetInpatientResponse GetInpatient(long wardId)
        {
            var azUser = AzUser.GetInApi(Request);

            var wardPatient = _ctx.HospWardPatients.FirstOrDefault(x => x.Id == wardId && x.WxUserId == azUser.UserId);

            if (wardPatient == null)
            {
                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到住院号"
                };
            }

            //获取住院号是否有效(只能查询在院患者)
            //获取院内webservice
            var request4GetZyhValid = new Request4GetZyhValid();
            request4GetZyhValid.WardNo = wardPatient.WardNo;


            Response4GetZyhValid response4GetZyhValid;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg4GetZyhValid = httpClient.PostAsJsonAsync("HisWs/GetZyhValid", request4GetZyhValid).Result;
                responseMsg4GetZyhValid.EnsureSuccessStatusCode();
                response4GetZyhValid = responseMsg4GetZyhValid.Content.ReadAsAsync<Response4GetZyhValid>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内 GetZyhValid Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = "获取住院记录超时"
                };
            }

            //获取院内webservice信息时出现错误 (院内webservice层错误)
            if (response4GetZyhValid.ResultCode != "0")
            {
                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = response4GetZyhValid.ResultDesc
                };
            }

            if (string.IsNullOrEmpty(response4GetZyhValid.FlowNo))
            {
                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = "没有查询到相关记录"
                };
            }

            //获取院内webservice
            var request4GetWardRecord = new Request4GetWardRecord();
            request4GetWardRecord.HosPatId = "";
            request4GetWardRecord.IdCard = "";
            request4GetWardRecord.FlowNo = "";
            request4GetWardRecord.WardNo = wardPatient.WardNo;


            Response4GetWardRecord response4GetWardRecord;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg4GetWardRecord = httpClient.PostAsJsonAsync("HisWs/GetWardRecord", request4GetWardRecord).Result;
                responseMsg4GetWardRecord.EnsureSuccessStatusCode();
                response4GetWardRecord = responseMsg4GetWardRecord.Content.ReadAsAsync<Response4GetWardRecord>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内 GetWardRecord Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = "获取住院记录超时"
                };
            }

            //获取院内webservice信息时出现错误 (院内webservice层错误)
            if (response4GetWardRecord.ResultCode != "0")
            {
                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = response4GetWardRecord.ResultDesc
                };
            }

            if (response4GetWardRecord.WardRecordList.Count == 0)
            {
                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = "没有查询到相关记录"
                };
            }

            var wardRecordList = response4GetWardRecord.WardRecordList.Select(x =>
                new
                {
                    x.FlowNo,
                    x.WardNo,
                    x.Name,
                    x.Sex,
                    x.BirthDay,
                    InDate = x.InDate.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                    OutDate = string.IsNullOrEmpty(x.OutDate) ? "" : x.OutDate.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                    x.DeptName,
                    x.NurseDeptName,
                    x.DayCount,
                    x.Bed,
                    TotalAmt = x.TotalAmt.ToSingleOrDefault().ToString("F2"),
                    DepositAmt = x.DepositAmt.ToSingleOrDefault().ToString("F2"),
                    AvailableAmt = x.AvailableAmt.ToSingleOrDefault().ToString("F2"),
                    PayTime = string.IsNullOrEmpty(x.PayTime) ? "" : x.PayTime.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                    x.PayType
                }).ToList();

            var wardRecord = wardRecordList.First();
            var flowNo = wardRecord.FlowNo;
            var startTime = wardRecord.InDate.ToDateTimeOrDefault().ToString("yyyy-MM-dd");
            var endTime = string.IsNullOrEmpty(wardRecord.OutDate) ? DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd") + " 23:59:59"
                : wardRecord.OutDate.ToDateTimeOrDefault().ToString("yyyy-MM-dd") + " 23:59:59";

            //获取每天的费用记录
            //获取院内webservice
            var request4GetWardDayAmt = new Request4GetWardDayAmt();
            request4GetWardDayAmt.FlowNo = flowNo;
            request4GetWardDayAmt.StartTime = startTime;
            request4GetWardDayAmt.EndTime = endTime;

            Response4GetWardDayAmt response4GetWardDayAmt;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg4GetWardDayAmt = httpClient.PostAsJsonAsync("HisWs/GetWardDayAmt", request4GetWardDayAmt).Result;
                responseMsg4GetWardDayAmt.EnsureSuccessStatusCode();
                response4GetWardDayAmt = responseMsg4GetWardDayAmt.Content.ReadAsAsync<Response4GetWardDayAmt>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内 GetWardDayAmt Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = "获取住院记录超时"
                };
            }

            //获取院内webservice信息时出现错误 (院内webservice层错误)
            if (response4GetWardDayAmt.ResultCode != "0")
            {
                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = response4GetWardRecord.ResultDesc
                };
            }

            if (response4GetWardDayAmt.WardDayAmtList.Count == 0)
            {
                return new GetInpatientResponse
                {
                    ResultCode = "1",
                    ResultMsg = "没有查询到相关记录"
                };
            }

            var wardDayAmtList = response4GetWardDayAmt.WardDayAmtList.OrderBy(x => x.BillDate).Select(x =>
               new GetInpatientResponse.WardDayAmt
               {
                   FlowNo = x.FlowNo,
                   DeptName = x.DeptName,
                   NurseDeptName = x.NurseDeptName,
                   Bed = x.Bed,
                   Amt = x.Amt.ToSingleOrDefault().ToString("F2"),
                   BillDate = x.BillDate,
               }).ToList();

            return new GetInpatientResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                FlowNo = wardRecord.FlowNo,
                WardNo = wardRecord.WardNo,
                Name = wardRecord.Name,
                Sex = wardRecord.Sex,
                BirthDay = wardRecord.BirthDay,
                InDate = wardRecord.InDate,
                OutDate = wardRecord.OutDate,
                DeptName = wardRecord.DeptName,
                NurseDeptName = wardRecord.NurseDeptName,
                DayCount = wardRecord.DayCount,
                Bed = wardRecord.Bed,
                TotalAmt = wardRecord.TotalAmt,
                DepositAmt = wardRecord.DepositAmt,
                AvailableAmt = wardRecord.AvailableAmt,
                PayTime = wardRecord.PayTime,
                PayType = wardRecord.PayType,
                WardDayAmtList = wardDayAmtList
            };
        }

        /// <summary>
        /// 获取每日住院费用
        /// </summary>
        /// <param name="flowNo"></param>
        /// <param name="billDate"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetDailyBill")]
        public GetDailyBillResponse GetDailyBill(string flowNo, string billDate)
        {
            var request = new Request4GetWardFeeDetail();
            request.FlowNo = flowNo;
            request.StartTime = billDate + " 00:00:00";
            request.EndTime = billDate + " 23:59:59";

            Response4GetWardFeeDetail response4GetWardFeeDetail;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetWardFeeDetail", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetWardFeeDetail = responseMsg.Content.ReadAsAsync<Response4GetWardFeeDetail>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内GetWardFeeDetail Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetDailyBillResponse
                {
                    ResultCode = "1",
                    ResultMsg = "获取住院每日费用分类信息"
                };
            }

            if (response4GetWardFeeDetail.ResultCode != "0")
            {
                return new GetDailyBillResponse
                {
                    ResultCode = "2",
                    ResultMsg = response4GetWardFeeDetail.ResultDesc
                };
            }

            var res = new GetDailyBillResponse();
            res.ResultCode = "0";
            res.ResultMsg = "";
            res.WardFeeDetailList = new List<GetDailyBillResponse.WardFeeDetail>();

            var response4WardFeeDetailList = response4GetWardFeeDetail.WardFeeDetailList.OrderBy(x => x.FeeType);

            foreach (var wardFeeDetail in response4WardFeeDetailList)
            {
                res.WardFeeDetailList.Add(new GetDailyBillResponse.WardFeeDetail
                {
                    FlowNo = wardFeeDetail.FlowNo,
                    FeeType = wardFeeDetail.FeeType,
                    FeeName = wardFeeDetail.FeeName,
                    FeeCode = wardFeeDetail.FeeCode,
                    Price = wardFeeDetail.Price.ToSingleOrDefault().ToString("F2"),
                    Spec = wardFeeDetail.Spec,
                    Unit = wardFeeDetail.Unit,
                    Qty = wardFeeDetail.Qty,
                    Amt = wardFeeDetail.Amt.ToSingleOrDefault().ToString("F2"),
                    BillDate = wardFeeDetail.BillDate,
                    FeeState = wardFeeDetail.FeeState == "0" ? "已结算" : "未结算",
                });
            }

            return res;
        }


        /// <summary>
        /// 获取住院病人预交金缴纳记录
        /// </summary>
        /// <param name="wardId"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetInpatientPrepayList")]
        public GetInpatientPrepayListResponse GetInpatientPrepayList(long wardId)
        {
            var azUser = AzUser.GetInApi(Request);

            var wardPatient = _ctx.HospWardPatients.FirstOrDefault(x => x.Id == wardId && x.WxUserId == azUser.UserId);

            if (wardPatient == null)
            {
                return new GetInpatientPrepayListResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到住院号"
                };
            }

            //获取住院号是否有效(只能查询在院患者)
            //获取院内webservice
            var request4GetZyhValid = new Request4GetZyhValid();
            request4GetZyhValid.WardNo = wardPatient.WardNo;


            Response4GetZyhValid response4GetZyhValid;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg4GetZyhValid = httpClient.PostAsJsonAsync("HisWs/GetZyhValid", request4GetZyhValid).Result;
                responseMsg4GetZyhValid.EnsureSuccessStatusCode();
                response4GetZyhValid = responseMsg4GetZyhValid.Content.ReadAsAsync<Response4GetZyhValid>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内 GetZyhValid Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetInpatientPrepayListResponse
                {
                    ResultCode = "1",
                    ResultMsg = "服务器或网络异常，请联系客服！"
                };
            }

            //获取院内webservice信息时出现错误 (院内webservice层错误)
            if (response4GetZyhValid.ResultCode != "0")
            {
                return new GetInpatientPrepayListResponse
                {
                    ResultCode = "1",
                    ResultMsg = response4GetZyhValid.ResultDesc
                };
            }

            var flowNo = response4GetZyhValid.FlowNo;

            if (string.IsNullOrEmpty(flowNo))
            {
                return new GetInpatientPrepayListResponse
                {
                    ResultCode = "1",
                    ResultMsg = "没有查询到相关记录"
                };
            }

            //获取住院病人预交金
            //获取院内webservice
            var request4GetWardDeposit = new Request4GetWardDeposit();
            request4GetWardDeposit.FlowNo = flowNo;

            Response4GetWardDeposit response4GetWardDeposit;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg4GetWardDeposit = httpClient.PostAsJsonAsync("HisWs/GetWardDeposit", request4GetWardDeposit).Result;
                responseMsg4GetWardDeposit.EnsureSuccessStatusCode();
                response4GetWardDeposit = responseMsg4GetWardDeposit.Content.ReadAsAsync<Response4GetWardDeposit>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内 GetWardDeposit Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetInpatientPrepayListResponse
                {
                    ResultCode = "1",
                    ResultMsg = "服务器或网络异常，请联系客服！"
                };
            }

            //获取院内webservice信息时出现错误 (院内webservice层错误)
            if (response4GetWardDeposit.ResultCode != "0")
            {
                return new GetInpatientPrepayListResponse
                {
                    ResultCode = "1",
                    ResultMsg = response4GetZyhValid.ResultDesc
                };
            }

            var wardPrepayList =
                response4GetWardDeposit.WardDepositList.OrderByDescending(x => x.PayDate)
                .Select(x => new GetInpatientPrepayListResponse.WardDeposit
                {
                    FlowNo = x.FlowNo,
                    DepositNo = x.DepositNo,
                    Amt = x.Amt,
                    PayDate = x.PayDate.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                    State = x.State
                }).OrderByDescending(x => x.PayDate).ToList();

            return new GetInpatientPrepayListResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                WardDeposits = wardPrepayList
            };
        }

        /// <summary>
        /// 获取住院预缴金信息
        /// </summary>
        /// <param name="wardId"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetInpatientPrepayInfo")]
        public GetInpatientPrepayInfoResponse GetInpatientPrepayInfo(long wardId)
        {
            var azUser = AzUser.GetInApi(Request);

            var wardPatient = _ctx.HospWardPatients.FirstOrDefault(x => x.Id == wardId && x.WxUserId == azUser.UserId);

            if (wardPatient == null)
            {
                return new GetInpatientPrepayInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到住院号"
                };
            }

            //获取住院号是否有效(只能查询在院患者)
            //获取院内webservice
            var request4GetZyhValid = new Request4GetZyhValid();
            request4GetZyhValid.WardNo = wardPatient.WardNo;

            Response4GetZyhValid response4GetZyhValid;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg4GetZyhValid = httpClient.PostAsJsonAsync("HisWs/GetZyhValid", request4GetZyhValid).Result;
                responseMsg4GetZyhValid.EnsureSuccessStatusCode();
                response4GetZyhValid = responseMsg4GetZyhValid.Content.ReadAsAsync<Response4GetZyhValid>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内 GetZyhValid Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetInpatientPrepayInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = "获取住院记录超时"
                };
            }

            //获取院内webservice信息时出现错误 (院内webservice层错误)
            if (response4GetZyhValid.ResultCode != "0")
            {
                return new GetInpatientPrepayInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = response4GetZyhValid.ResultDesc
                };
            }

            if (string.IsNullOrEmpty(response4GetZyhValid.FlowNo))
            {
                return new GetInpatientPrepayInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = "没有查询到相关记录"
                };
            }

            //获取院内webservice
            var request4GetWardRecord = new Request4GetWardRecord();
            request4GetWardRecord.HosPatId = "";
            request4GetWardRecord.IdCard = "";
            request4GetWardRecord.FlowNo = "";
            request4GetWardRecord.WardNo = wardPatient.WardNo;


            Response4GetWardRecord response4GetWardRecord;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg4GetWardRecord = httpClient.PostAsJsonAsync("HisWs/GetWardRecord", request4GetWardRecord).Result;
                responseMsg4GetWardRecord.EnsureSuccessStatusCode();
                response4GetWardRecord = responseMsg4GetWardRecord.Content.ReadAsAsync<Response4GetWardRecord>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内 GetWardRecord Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetInpatientPrepayInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = "获取住院记录超时"
                };
            }

            //获取院内webservice信息时出现错误 (院内webservice层错误)
            if (response4GetWardRecord.ResultCode != "0")
            {
                return new GetInpatientPrepayInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = response4GetWardRecord.ResultDesc
                };
            }

            if (response4GetWardRecord.WardRecordList.Count == 0)
            {
                return new GetInpatientPrepayInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = "没有查询到相关记录"
                };
            }

            var wardRecordList = response4GetWardRecord.WardRecordList.Select(x =>
                new
                {
                    x.FlowNo,
                    x.WardNo,
                    x.Name,
                    x.Sex,
                    x.BirthDay,
                    InDate = x.InDate.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                    OutDate = string.IsNullOrEmpty(x.OutDate) ? "" : x.OutDate.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                    x.DeptName,
                    x.NurseDeptName,
                    x.DayCount,
                    x.Bed,
                    TotalAmt = x.TotalAmt.ToSingleOrDefault().ToString("F2"),
                    DepositAmt = x.DepositAmt.ToSingleOrDefault().ToString("F2"),
                    AvailableAmt = x.AvailableAmt.ToSingleOrDefault().ToString("F2"),
                    PayTime = string.IsNullOrEmpty(x.PayTime) ? "" : x.PayTime.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                    x.PayType
                }).ToList();

            var wardRecord = wardRecordList.First();

            return new GetInpatientPrepayInfoResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                FlowNo = wardRecord.FlowNo,
                WardNo = wardRecord.WardNo,
                Name = wardRecord.Name,
                Sex = wardRecord.Sex,
                BirthDay = wardRecord.BirthDay,
                InDate = wardRecord.InDate,
                OutDate = wardRecord.OutDate,
                DeptName = wardRecord.DeptName,
                NurseDeptName = wardRecord.NurseDeptName,
                DayCount = wardRecord.DayCount,
                Bed = wardRecord.Bed,
                TotalAmt = wardRecord.TotalAmt,
                DepositAmt = wardRecord.DepositAmt,
                AvailableAmt = wardRecord.AvailableAmt,
                PayTime = wardRecord.PayTime,
                PayType = wardRecord.PayType
            };
        }

        [HttpGet]
        [ActionName("CreatePrepayOrder")]
        public CreatePrepayOrderResponse CreatePrepayOrder(long wardId, string prepayMoney)
        {
            var azUser = AzUser.GetInApi(Request);
            var ward = _ctx.HospWardPatients.FirstOrDefault(x => x.Id == wardId && x.WxUserId == azUser.UserId);
            if (ward == null)
            {
                return new CreatePrepayOrderResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到住院号信息"
                };
            }

            var intMoney = prepayMoney.ToDecimalOrDefault();
            if (intMoney <= 0)
            {
                return new CreatePrepayOrderResponse
                {
                    ResultCode = "2",
                    ResultMsg = "充值金额必须大于零"
                };
            }

            var newPrepayOrder = new InpatientPrepayOrder()
            {
                WxUserId = azUser.UserId,
                PatientName = ward.Name,
                CreateTime = DateTime.Now,
                PayState = PrepayOrderExtensions.PayState.未付款.ToInt32().ToString(),
                OrderStatus = PrepayOrderExtensions.OrderStatus.未支付.ToInt32(),
                WardNo = ward.WardNo,
                PrepayMoney = prepayMoney.ToDecimalOrDefault(),
                OrderNo = GenerateNewOrderNo()
            };

            _ctx.InpatientPrepayOrders.Add(newPrepayOrder);
            _ctx.SaveChanges();

            newPrepayOrder.OrderStatus = BillOrderExtensions.OrderStatus.支付中.ToInt32();
            _ctx.SaveChanges();

            // RMQ 16分钟后如果还是支付中则设置支付失败
            var payingTimeoutProducer = new OrderPayingTimeoutProducer();
            payingTimeoutProducer.Publish(new OrderPayingTimeoutMsg
            {
                OrderType = OrderType.住院预缴金订单,
                OrderId = newPrepayOrder.Id
            }, 16 * 60 * 1000);

            //组织 微信 js 支付方法 getBrandWCPayRequest 的参数
            var payStartTime = System.DateTime.Now.ToString("yyyyMMddHHmmss");
            var payExpireTime = System.DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss");

            var payFee = (newPrepayOrder.PrepayMoney * 100).ToInt32().ToString();
            var superWxUserIds = WebConfigurationManager.AppSettings["UserIdsForPayMin"].Split(" , ",
                StringSplitOptions.RemoveEmptyEntries);
            if (newPrepayOrder.WxUserId.HasValue && superWxUserIds.Contains(newPrepayOrder.WxUserId.ToStringOrDefault()))
            {
                payFee = "1";
            }

            var result = WeixinPayV3Helper.ComposeJsApiParameter("住院预缴金", "IP" + newPrepayOrder.OrderNo,
                  payFee, GetClientIp(), payStartTime, payExpireTime, "Inpatient/PaySucceed", azUser.OpenId);

            if (result.ResultCode != "0")
            {
                return new CreatePrepayOrderResponse
                {
                    ResultCode = "1",
                    ResultMsg = result.ResultMsg
                };
            }

            return new CreatePrepayOrderResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                PayString = result.Parameter,
                OrderId = newPrepayOrder.Id,
                OrderNo = newPrepayOrder.OrderNo
            };
        }

        /// <summary>
        /// 用户取消支付
        /// </summary>
        /// <param name="orderId">订单id</param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("PayFailed")]
        public PayFailedResponse PayFailed(int orderId)
        {
            var azUser = AzUser.GetInApi(Request);

            var order = _ctx.InpatientPrepayOrders.IsStatus(PrepayOrderExtensions.OrderStatus.支付中)
                .FirstOrDefault(x => x.WxUserId == azUser.UserId && x.Id == orderId);
            if (order == null)
            {
                return new PayFailedResponse
                {
                    ResultCode = "1",
                    ResultMsg = "订单不存在"
                };
            }

            order.OrderStatus = PrepayOrderExtensions.OrderStatus.支付失败.ToInt32();
            _ctx.SaveChanges();

            return new PayFailedResponse
            {
                ResultCode = "0",
                ResultMsg = ""
            };
        }

        /// <summary>
        /// 微信支付通知回调
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        [ActionName("PaySucceed")]
        public HttpResponseMessage PaySucceed()
        {
            var result = WeixinPayV3Helper.ParsePayNotify(Request.RequestUri, Request.Content.ReadAsStringAsync().Result.Copy());

            if (result.ResultCode == "0")//成功
            {
                var transactionId = result.PayOrder.TransactionId;
                lock (PayNotifyLocker)
                {
                    if (_ctx.WxPayNotifyLogs.Any(x => x.TransactionId == transactionId && x.TradeState == 0))
                    {
                        return new HttpResponseMessage
                        {
                            StatusCode = HttpStatusCode.OK,
                            Content = new StringContent(result.SuccessResponse)
                        };
                    }

                    //记录通过验证的支付通知
                    var orderNotifyLog = new WxPayNotifyLog
                    {
                        ServiceVersion = result.PayOrder.ServiceVersion,
                        Attach = result.PayOrder.Attach,
                        BankBillNo = result.PayOrder.BankBillNo,
                        BankType = result.PayOrder.BankType,
                        BuyerAlias = result.PayOrder.BuyerAlias,
                        Discount = result.PayOrder.Discount.ToNullableInt32(),
                        //FeeType = result.PayOrder.FeeType.ToNullableInt32(),
                        InputCharset = result.PayOrder.InputCharset,
                        NotifyId = result.PayOrder.NotifyId,
                        SignType = result.PayOrder.SignType,
                        Sign = result.PayOrder.Sign,
                        SignKeyIndex = result.PayOrder.SignKeyIndex.ToNullableInt32(),
                        //TradeMode = result.PayOrder.TradeMode.ToNullableInt32(),
                        TradeState = result.PayOrder.TradeState.ToNullableInt32(),
                        PayInfo = result.PayOrder.PayInfo,
                        Partner = result.PayOrder.Partner,
                        TotalFee = result.PayOrder.TotalFee.ToNullableInt32(),
                        TransactionId = result.PayOrder.TransactionId,
                        OutTradeNo = result.PayOrder.OutTradeNo,
                        TimerEnd = result.PayOrder.TimeEnd,
                        TransportFee = result.PayOrder.TransportFee.ToNullableInt32(),
                        ProductFee = result.PayOrder.ProductFee.ToNullableInt32(),
                        PostAppId = result.PayUser.AppId,
                        PostTimeStamp = result.PayUser.TimeStamp,
                        PostNonceStr = result.PayUser.NonceStr,
                        PostOpenId = result.PayUser.OpenId,
                        PostAppSignature = result.PayUser.AppSignature,
                        PostIsSubscribe = result.PayUser.IsSubscribe,
                        RecCreateDt = DateTime.Now,
                        Uri = Request.RequestUri.AbsoluteUri,
                        IsVerified = 1
                    };

                    _ctx.WxPayNotifyLogs.Add(orderNotifyLog);
                    _ctx.SaveChanges();
                }

                if (result.PayOrder.TradeState == "0")
                {
                    //处理订单 并记录日志
                    if (result.PayOrder.OutTradeNo.StartsWith("IP"))
                    {
                        var orderNo = result.PayOrder.OutTradeNo.Substring(2);
                        var order = _ctx.InpatientPrepayOrders.FirstOrDefault(x => x.OrderNo == orderNo);
                        if (order != null)
                        {
                            var isFromRefundUserId = false;
                            if (order.WxUserId.HasValue)
                            {
                                var refundWxUserIds = WebConfigurationManager.AppSettings["UserIdsForMustRefund"].Split(" , ",
                                StringSplitOptions.RemoveEmptyEntries);
                                isFromRefundUserId = refundWxUserIds.Contains(order.WxUserId.ToStringOrDefault());
                            }

                            if (order.OrderStatus == PrepayOrderExtensions.OrderStatus.支付中.ToInt32())
                            {
                                order.PayState = PrepayOrderExtensions.PayState.已付款.ToInt32().ToString();
                                order.PayTime = DateTime.ParseExact(result.PayOrder.TimeEnd, "yyyyMMddHHmmss",
                                    CultureInfo.CurrentCulture);
                                order.WxTransactionId = transactionId;
                                order.OrderStatus = PrepayOrderExtensions.OrderStatus.支付成功.ToInt32();
                                _ctx.SaveChanges();

                                //必退的UserId,执行退费操作
                                if (isFromRefundUserId)
                                {
                                    //His缴费失败，执行退款操作
                                    var refundingProducer = new OrderRefundingPickupFailedProducer();
                                    refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                                    {
                                        OrderType = OrderType.住院预缴金订单,
                                        OrderId = order.Id
                                    });
                                }
                                else
                                {
                                    // RMQ 执行缴纳预缴金操作
                                    var pickupingProducer = new OrderPickupingProducer();
                                    pickupingProducer.Publish(new OrderPickupingMsg
                                    {
                                        OrderType = Rmq.Center.OrderType.住院预缴金订单,
                                        OrderId = order.Id
                                    });
                                }
                            }
                            else if (order.OrderStatus ==
                                     PrepayOrderExtensions.OrderStatus.缴费失败.ToInt32())
                            {
                                //His缴费失败，执行退款操作
                                var refundingProducer = new OrderRefundingPickupFailedProducer();
                                refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                                {
                                    OrderType = OrderType.住院预缴金订单,
                                    OrderId = order.Id
                                });
                            }
                        }
                    }
                }

                return new HttpResponseMessage
                {
                    StatusCode = HttpStatusCode.OK,
                    Content = new StringContent(result.SuccessResponse)
                };
            }

            #region 记录验证失败的支付通知

            var unverifiedNotifyLog = new WxPayNotifyLog
            {
                Uri = Request.RequestUri.AbsoluteUri,
                IsVerified = 0,
                RecCreateDt = DateTime.Now
            };
            _ctx.WxPayNotifyLogs.Add(unverifiedNotifyLog);
            _ctx.SaveChanges();

            #endregion

            return new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent(result.FailResponse)
            };
        }

        /// <summary>
        /// 获取预缴金缴纳状态
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetPrepayStatus")]
        public GetPrepayStatusResponse GetPrepayStatus(int orderId)
        {
            var azUser = AzUser.GetInApi(Request);
            var order = _ctx.InpatientPrepayOrders.FirstOrDefault(x => x.Id == orderId && x.WxUserId == azUser.UserId);
            if (order == null)
            {
                return new GetPrepayStatusResponse
                {
                    ResultCode = "1",
                    ResultMsg = "订单不存在"
                };
            }

            if (order.OrderStatus == PrepayOrderExtensions.OrderStatus.缴费中.ToInt32()
                || order.OrderStatus == PrepayOrderExtensions.OrderStatus.支付中.ToInt32()
                || order.OrderStatus == PrepayOrderExtensions.OrderStatus.支付成功.ToInt32())
            {
                return new GetPrepayStatusResponse
                {
                    ResultCode = "0",
                    ResultMsg = "",
                    PrepayStatus = "2",
                    FailedMsg = ""
                };
            }

            if (order.OrderStatus == PrepayOrderExtensions.OrderStatus.缴费成功.ToInt32())
            {
                return new GetPrepayStatusResponse
                {
                    ResultCode = "0",
                    ResultMsg = "",
                    PrepayStatus = "0",
                    FailedMsg = ""
                };
            }

            return new GetPrepayStatusResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                PrepayStatus = "1",
                FailedMsg = ""
            };
        }


        [HttpGet]
        [ActionName("GetPrepayOrderDetail")]
        public GetPrepayOrderDetailResponse GetPrepayOrderDetail(int orderId)
        {
            var azUser = AzUser.GetInApi(Request);
            var order = _ctx.InpatientPrepayOrders.FirstOrDefault(x => x.Id == orderId && x.WxUserId == azUser.UserId);
            if (order == null)
            {
                return new GetPrepayOrderDetailResponse
                {
                    ResultCode = "1",
                    ResultMsg = "订单不存在"
                };
            }

            return new GetPrepayOrderDetailResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                Id = order.Id,
                OrderNo = order.OrderNo,
                WardNo = order.WardNo,
                PatientName = order.PatientName,
                CreateDt = order.CreateTime.GetValueOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                PrepayMoney = order.PrepayMoney.GetValueOrDefault().ToString("F2")
            };
        }

        public string GenerateNewOrderNo()
        {
            var orderNo = "WX" + DateTime.Now.Date.ToString("yyyyMMdd");
            lock (OrderNoLocker)
            {
                orderNo += (DateTime.Now - DateTime.Now.Date).TotalMilliseconds.ToString("00000000");
                Thread.Sleep(1);
            }

            return orderNo;
        }

        public string GetClientIp()
        {
            if (Request.Properties.ContainsKey("MS_HttpContext"))
            {
                string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                //判断是否有代理服务器
                if (string.IsNullOrEmpty(ip))
                {
                    //没有代理服务器,如果有代理服务器获取的是代理服务器的IP
                    ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                }

                string pattrn = @"(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])";
                if (!string.IsNullOrEmpty(ip) && System.Text.RegularExpressions.Regex.IsMatch(ip, pattrn))
                {
                    return ip;
                }

                return "127.0.0.1";
            }
            else
            {
                return "127.0.0.1";
            }
        }
    }
}
